#!/usr/bin/env python3
#
# power_function.py
#


from matplotlib.ticker import FuncFormatter
from matplotlib.ticker import MultipleLocator
import matplotlib.pyplot as plt
import numpy as np


def main():

    fig, ax = plt.subplots(figsize=(8,8))

    ax = configure_axes(ax, 'Power Function', 5, 5, 1, 0.25, 1, 0.25)

    x = np.linspace(-5.3, 5.3, 100)
    y = x
    ax.plot(x, x, color='g')
    ax.text(5.0, 5.2,  r'$y = x$',  color='g', horizontalalignment='right',  verticalalignment='bottom')

    x = np.linspace(-2.302, 2.302, 100)
    y = np.power(x, 2)
    ax.plot(x, y, color='r')
    ax.text(2.6, 5.2,  r'$y = x^2$',  color='r', horizontalalignment='left',  verticalalignment='bottom')

    x = np.linspace(-1.743, 1.743, 100)
    y = np.power(x, 3)
    ax.plot(x, y, color='b')
    ax.text(1.6, 5.2,  r'$y = x^3$',  color='b', horizontalalignment='right',  verticalalignment='bottom')

    x = np.linspace(0, 5.3, 100)
    y = np.power(x, 1/2)
    ax.plot(x, y, color='y')
    ax.text(5.2, 2.3,  r'$y = x^\frac{1}{2}$',  color='y', horizontalalignment='right',  verticalalignment='bottom')

    x1 = np.linspace(0.188, 5.3, 100)
    y1 = np.power(x1, -1)
    x2 = np.linspace(-0.188,-5.3,100)
    y2 = np.power(x2, -1)
    ax.plot(x1, y1, x2, y2, color='k')
    ax.text(5.2, 0.3,  r'$y = x^{-1}$',  color='k', horizontalalignment='right',  verticalalignment='bottom')

    fig.tight_layout()

    plt.show()
    # end of main()


def configure_axes(ax, title, xlimit, ylimit, xmajorunit = 5, xminorunit = 1, ymajorunit = 5, yminorunit = 1):

    ax.set_title(title, fontsize='large', loc='left')

    ax.spines['left'].set_position('zero')
    ax.spines['right'].set_visible(False)
    ax.spines['bottom'].set_position('zero')
    ax.spines['top'].set_visible(False)

    ax.text(-0.2, -0.2, 'O', fontsize='x-large', fontstyle='italic', horizontalalignment='right', verticalalignment='top')

    xlimit += xmajorunit*0.8
    ylimit += ymajorunit*0.8
    ax.set_xlim((-xlimit, xlimit))
    ax.set_ylim((-ylimit, ylimit))

    ax.plot(1, 0, '>k', transform=ax.get_yaxis_transform(), clip_on=False)
    ax.xaxis.set_label_text('x')
    ax.xaxis.set_label_coords(1.01, 0.48)
    ax.xaxis.set_major_formatter(FuncFormatter(lambda w, pos: int(w) if w else ''))
    ax.xaxis.set_major_locator(MultipleLocator(xmajorunit))
    ax.xaxis.set_minor_locator(MultipleLocator(xminorunit))
    ax.xaxis.set_tick_params(which='both', direction='in')

    ax.plot(0, 1, '^k', transform=ax.get_xaxis_transform(), clip_on=False)
    ax.yaxis.set_label_text('y')
    ax.yaxis.set_label_coords(0.48, 1)
    ax.yaxis.label.set_rotation(0)
    ax.yaxis.set_major_formatter(FuncFormatter(lambda w, pos: int(w) if w else ''))
    ax.yaxis.set_major_locator(MultipleLocator(ymajorunit))
    ax.yaxis.set_minor_locator(MultipleLocator(yminorunit))
    ax.yaxis.set_tick_params(which='both', direction='in')

    return ax
    # end of configure_axes()


if __name__ == '__main__': main()

